<script setup lang="ts">
import { onMounted, onUnmounted, ref, nextTick, provide } from 'vue'
import RoomStatus from './components/RoomStatus.vue'
import RoomAction from './components/RoomAction.vue'
import RoomMessage from './components/RoomMessage.vue'

import { io, type Socket } from 'socket.io-client'
import { baseURL } from '@/utils/request'
import { useUserStore } from '@/stores'
import { useRoute } from 'vue-router'
import type { Message, TimeMessages } from '@/types/room'
import { MsgType, OrderType } from '@/enums'
import { getConsultOrderDetail } from '@/api/consult'
import type { ConsultOrderItem, Image } from '@/types/consult'

// 1. ws服务器建立连接（浏览器给ws服务器打电话）
const store = useUserStore()
const route = useRoute()
// 消息列表
const list = ref<Message[]>([])
// 存储ws实例
let ws: Socket
// 建立连接方法
const initWs = () => {
  ws = io(baseURL, {
    auth: {
      // 携带token,后台校验
      token: `Bearer ${store.user.token}`
    },
    query: {
      // 携带订单ID
      orderId: route.query.orderId
    }
  })
  ws.on('connect', () => {
    console.log('连接建立成功！')
  })
  ws.on('error', () => {
    console.log('连接建立失败！')
  })

  /**
   * 获取ws服务器发送的默认消息
   */
  ws.on('chatMsgList', (res) => {
    console.log('ws服务器发送的默认消息：', res.data)
    const historyData: TimeMessages[] = res.data
    // 处理res.data数据格式,满足渲染需要
    const result: Message[] = []
    historyData.forEach((item) => {
      // 1. 处理默认消息的时间，把时间也处理成一条消息
      result.push({
        id: item.createTime,
        msgType: MsgType.Notify, // 通用通知消息
        msg: {
          content: item.createTime
        },
        createTime: item.createTime
      })
      // 2. 处理item消息
      result.push(...item.items)
    })
    console.log('处理完的消息：', result)
    list.value = result
  })

  // 接收消息=> 发送的消息和医生回复消息
  ws.on('receiveChatMsg', async (msg) => {
    console.log('发送的消息和医生回复消息:', msg)
    list.value.push(msg)
    // 背景：修改数据后，dom更新异步的
    // nextTick作用：等到数据渲染完执行，执行后续代码
    // vue2: this.$nextTick()
    // vue3: nextTick()
    await nextTick()
    // document.body.scrollHeight聊天列表滚动高度
    // 每次都滚动到列表的最底部，避免聊天内容被遮盖
    window.scrollTo(0, document.body.scrollHeight)
  })

  // 3. 监听超级医生订单状态变更，更新订单状态（必须）
  ws.on('statusChange', async () => {
    console.log('医生接单了：订单状态需要重新发送请求！')
    getConsult()
  })
}
// 组件挂载后建立连接
onMounted(() => {
  initWs()
})
// 组件销毁断开连接=>离开问诊室
onUnmounted(() => {
  ws.close()
})

// 2. 发送文字消息
// 挂号订单详情数据
const consult = ref<ConsultOrderItem>()
// 获取挂号订单详情数据
const getConsult = async () => {
  const res = await getConsultOrderDetail(route.query.orderId as string)
  consult.value = res
  console.log('挂号订单详情：', consult.value)
}
const sendText = (msg: string) => {
  console.log('收到子组件发送文字消息：', msg)
  ws.emit('sendChatMsg', {
    from: store.user.id, // 发送人(患者)
    to: consult.value?.docInfo?.id, // 收消息人(医生)
    msgType: MsgType.MsgText, // 消息类型:文字消息
    msg: { content: msg } // 消息内容
  })
}
onMounted(() => {
  getConsult()
})
// 3. 发送图片消息
const sendImg = (img: Image) => {
  ws.emit('sendChatMsg', {
    from: store.user.id, // 发送人(患者)
    to: consult.value?.docInfo?.id, // 收消息人(医生)
    msgType: MsgType.MsgImage, // 消息类型:图片消息
    msg: {
      picture: img
    }
  })
}
// 4. 评价医生
// 注入：订单详情数据
// == 异步数据一定要注入响应式的 ==
// 问题：注入的时候consult.value不是响应式的=》需要注入consult响应变量
provide('consult', consult)
// 注入：评价成功，修改评价消息状态和数据(切换卡片展示)方法
const completeEva = (score: number) => {
  // 获取评价信息数据
  const item = list.value.find((item) => item.msgType === MsgType.CardEvaForm)
  if (item) {
    // 更新分数
    item.msg.evaluateDoc = { score }
    // 更新类型为已评价
    item.msgType = MsgType.CardEva
  }
}
provide('completeEva', completeEva)
</script>

<template>
  <div class="room-page">
    <!-- 导航栏 -->
    <cp-nav-bar title="医生问诊室" />
    <!-- 1. 问诊状态-->
    <room-status :status="consult?.status" :countdown="consult?.countdown" />
    <!-- 2. == 问诊聊天列表消息 == -->
    <room-message :list="list" />
    <!-- 3. 底部操作栏：发消息 
    说明：订单详情status状态不等于3就是医生没接诊
    -->
    <room-action
      @send-img="sendImg"
      :disabled="consult?.status !== OrderType.ConsultChat"
      @send-text="sendText"
    />
  </div>
</template>
<style lang="scss" scoped>
.room-page {
  padding-top: 90px;
  padding-bottom: 60px;
  min-height: 100vh;
  box-sizing: border-box;
  background-color: var(--cp-bg);
  .van-pull-refresh {
    width: 100%;
    min-height: calc(100vh - 150px);
  }
}
</style>
